package com.wenjie.databseDiff.handle.DatasourceSynchronizer.imp;

import cn.hutool.core.util.BooleanUtil;
import com.wenjie.databseDiff.enums.Drivers;
import com.wenjie.databseDiff.handle.DatasourceSynchronizer.AbstractDatasourceSynchronizer;
import com.wenjie.original.entity.SysDiffColumn;
import com.wenjie.original.entity.SysDiffTable;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * H2数据源同步
 *
 * @author wxg
 */
@Slf4j
public class H2DatasourceSynchronizer extends AbstractDatasourceSynchronizer {

    private static final String SQL_QUERY_TABLE = "select * from information_schema.tables where TABLE_SCHEMA='PUBLIC' and  table_catalog = ?";
    private static final String SQL_QUERY_COLUMN = "select *  from information_schema.columns where TABLE_SCHEMA='PUBLIC' and  table_catalog = ? and table_name=?";

    public H2DatasourceSynchronizer(String url, String user, String password) {
        super(url, user, password);
    }


    @Override
    public List<SysDiffTable> getTables(Connection connection, String database) {
        List<SysDiffTable> allTables = getAllTables(connection, database);
        log.info("Find {} tables", allTables.size());
        Map<String, List<String>> allTableIndexes = getAllTableIndexes(connection, database);
        log.info("Find {} indexes", allTableIndexes.size());
        for (SysDiffTable SysDiffTable : allTables) {
            List<String> indexes = allTableIndexes.get(SysDiffTable.getTableName());
            if (indexes != null) {
                SysDiffTable.setTableIndex(String.join("; ", indexes));
            }
        }
        return allTables;
    }

    private List<SysDiffTable> getAllTables(Connection connection, String database) {
        PreparedStatement statement;
        try {
            statement = connection.prepareStatement(SQL_QUERY_TABLE);
            statement.setString(1, database);
            ResultSet resultSet = statement.executeQuery();
            List<SysDiffTable> SysDiffTables = new ArrayList<>();
            while (resultSet.next()) {
                SysDiffTable SysDiffTable = new SysDiffTable();
                SysDiffTable.setTableName(resultSet.getString("TABLE_NAME"));
                SysDiffTable.setTableType(resultSet.getString("TABLE_TYPE"));
                SysDiffTable.setTableRows(resultSet.getLong("ROW_COUNT_ESTIMATE"));
                SysDiffTable.setTableComment(resultSet.getString("REMARKS"));
                SysDiffTable.setTableCollation(null);
                SysDiffTable.setCreateTime(null);
                SysDiffTable.setUpdateTime(null);
                SysDiffTable.setTableEngine(null);
                SysDiffTables.add(SysDiffTable);
            }
            return SysDiffTables;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    private Map<String, List<String>> getAllTableIndexes(Connection connection, String database) {
        Map<String, List<String>> indexMap = new HashMap<>();
        /*PreparedStatement statement;
        try {
            statement = connection.prepareStatement(SQL_QUERY_INDEX);
            statement.setString(1, database);
            List<String> indexes = new ArrayList<>();
            ResultSet indexResultSet = statement.executeQuery();
            while (indexResultSet.next()) {
                String tableName = indexResultSet.getString("TABLE_NAME");
                String indexName = indexResultSet.getString("INDEX_NAME");
                String indexColumn = indexResultSet.getString("COLUMNS");
                List<String> list = indexMap.computeIfAbsent(tableName, k -> new ArrayList<>());
                list.add(indexName + "(" + indexColumn + ")");
            }
            return indexMap;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }*/
        return indexMap;
    }

    @Override
    public List<SysDiffColumn> getColumns(Connection connection, String database, String tableName) {
        List<SysDiffColumn> SysDiffColumns = new ArrayList<>();
        PreparedStatement statement;
        try {
            statement = connection.prepareStatement(SQL_QUERY_COLUMN);

            statement.setString(1, database);
            statement.setString(2, tableName);
            ResultSet resultSet = statement.executeQuery();

            while (resultSet.next()) {
                SysDiffColumn SysDiffColumn = new SysDiffColumn();
                SysDiffColumn.setColumnName(resultSet.getString("COLUMN_NAME"));
                SysDiffColumn.setColumnSort(resultSet.getInt("ORDINAL_POSITION"));
                SysDiffColumn.setColumnDefault(resultSet.getObject("COLUMN_DEFAULT"));
                SysDiffColumn.setColumnDataType(resultSet.getString("DATA_TYPE"));
                //TODO 长度
                SysDiffColumn.setColumnType(resultSet.getString("DATA_TYPE"));
                SysDiffColumn.setColumnIndex(null);
                SysDiffColumn.setColumnNull(BooleanUtil.toBoolean(resultSet.getString("IS_NULLABLE")));
                SysDiffColumn.setColumnComment(resultSet.getString("REMARKS"));
                SysDiffColumn.setTableName(resultSet.getString("TABLE_NAME"));
                SysDiffColumns.add(SysDiffColumn);
            }
            return SysDiffColumns;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String getDriverFile() {
        return Drivers.H2.getDriver();
    }

    @Override
    public String getDriverClassName() {
        return Drivers.H2.getDriverClassName();
    }

}
